﻿
using Newtonsoft.Json.Linq;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using WebGrease.Css.Extensions;
using System.Net;
using System.Net.Sockets;
using YunShop_WebAPI.BLL.SxfPay;
using NPOI.SS.Formula.Functions;
using Org.BouncyCastle.Asn1.X500;
using System.Data.SqlClient;

namespace YunShop_WebAPI.BLL
{
    /// <summary>
    /// 随行付类
    /// </summary>
    public class SxfPayCommon
    {
        /// <summary>
        /// 随行付支付-建立支付
        /// </summary>
        /// <returns></returns>
        public static bool GetCreateOrderPay(int business_id, string openID, decimal amt, string ordNo,
            ref string msg, out Dictionary<string, object> Result, bool Query = true)
        {
            Result = new Dictionary<string, object>();//返回支付信息
            Hashtable ht = new Hashtable(); //创建一个Hashtable实例
            ht = GetPayParam(business_id, amt.ToString(), ordNo, openID);
            string requestMessage = getRequestPara(ht);
            string responseJson;
            try
            {
                responseJson = RequestClient.Post(SxfConfig.PayServiceUrl, requestMessage);
                Result = (Dictionary<String, Object>)LFTPayDoing.Json2Dictionary(responseJson);
            }
            catch (Exception ex)
            {
                msg = "SXF失败," + ex.Message;
                return false;
            }

            if (Query)
                return getPayResult(responseJson, amt.ToString(), ordNo, ref msg);
            else
                return false;
        }

        /// <summary>
        /// 随行付支付-建立退款
        /// </summary>
        /// <returns></returns>
        public static bool SetRefund(int business_id, string ordNo, string origOrderNo, decimal dAmount, ref string msg)
        {
            Dictionary<string, object> Result = new Dictionary<string, object>();
            Hashtable ht = new Hashtable(); //创建一个Hashtable实例
            ht = GetRefundParam(business_id, ordNo, origOrderNo, dAmount);

            string requestMessage = getRequestPara(ht);
            string responseJson;
            try
            {
                responseJson = RequestClient.Post("https://openapi.tianquetech.com/order/refund", requestMessage);
                IDictionary<string, object> respData = null;
                try
                {
                    respData = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, object>>(responseJson);
                    msg = respData["msg"].ToString();
                    if (respData["code"].ToString() == "0000")
                    {
                        string signResult = respData["respData"].ToString();
                        Hashtable row = (Hashtable)PluSoft.Utils.JSON.Decode(signResult);
                        string retCode = CommonFun.ConvertToString(row["bizCode"]);
                        if (retCode == "0000")
                        {
                            //msg = CommFunc.ConvertToString(row["bizMsg"]);
                            msg = "";
                            return true;
                        }
                        else if (retCode == "2002")
                        {
                            msg = CommonFun.ConvertToString(row["bizMsg"]);
                            return refundQuery(business_id, ordNo, ref msg);
                        }
                    }
                    return false;
                }
                catch (Exception ex)
                {
                    msg = ex.Message;
                    return false;
                }
            }
            catch (Exception ex)
            {
                msg = ex.Message;
                return false;
            }
        }

        //聚合支付参数设置
        public static Hashtable GetQueryParam(int business_id, string ordNo)
        {
            string sxf_mno = SxfConfig.getMechId(business_id);
            Hashtable ht = new Hashtable();
            ht.Add("mno", sxf_mno);
            ht.Add("ordNo", ordNo);
            return ht;
        }

        /// <summary>
        /// 退款查询
        /// </summary>
        /// <param name="ordNo"></param>
        /// <param name="msg"></param>
        /// <param name="TransactionID"></param>
        /// <param name="sTranSts"></param>
        /// <returns></returns>
        public static bool refundQuery(int business_id, string ordNo, ref string msg)
        {
            Dictionary<string, object> Result = new Dictionary<string, object>();
            Hashtable ht = new Hashtable(); //创建一个Hashtable实例
            ht = GetQueryParam(business_id, ordNo);

            string requestMessage = getRequestPara(ht);
            string responseJson = null;
            int mTimes = 0;
            try
            {
            WaitingStart:
                {
                    responseJson = RequestClient.Post("https://openapi.tianquetech.com/query/refundQuery", requestMessage);
                    IDictionary<string, object> respData = null;
                    respData = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, object>>(responseJson);
                    if (respData["code"].ToString() == "0000")
                    {
                        string signResult = respData["respData"].ToString();
                        Hashtable row = (Hashtable)PluSoft.Utils.JSON.Decode(signResult);
                        string sTranSts = CommonFun.ConvertToString(row["tranSts"]);
                        msg = CommonFun.ConvertToString(row["bizMsg"]);
                        switch (sTranSts)
                        {
                            case "REFUNDSUC"://退款成功
                                return true;
                            case "REFUNDFAIL"://交易失败
                                return false;
                            case "REFUNDING"://退款中
                                mTimes += 1;
                                System.Threading.Thread.Sleep(1000);
                                if (mTimes < 60) goto WaitingStart;
                                break;
                        }
                    }
                    return false;
                }
            }
            catch (Exception ex)
            {
                return false;
            }
        }


        //聚合支付参数设置
        public static Hashtable GetRefundParam(int business_id, string ordNo, string origOrderNo, decimal dAmount)
        {
            string sxf_mno = SxfConfig.getMechId(business_id);

            Hashtable ht = new Hashtable();
            ht.Add("ordNo", ordNo);
            ht.Add("origOrderNo", origOrderNo);
            ht.Add("mno", sxf_mno);
            //ht.Add("deviceNo", SysVar.mFPay_XJL_Key); //2022-04-23添加
            ht.Add("amt", dAmount);
            return ht;
        }

        /// <summary>
        /// 解析返回支付结果
        /// </summary>
        /// <returns></returns>
        public static object getPayResult(String responseJson, string sign_key, ref string msg)
        {
            IDictionary<string, object> respData = null;
            try
            {
                respData = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, object>>(responseJson);
                if (respData["code"].ToString() != "0000")
                {
                    msg = respData["msg"].ToString();
                    return false;
                }

                string signResult = respData["sign"].ToString();
                msg = respData["msg"].ToString();
                respData.Remove("sign");
                //参数签名串
                string resultStr = RSAUtil.GetSignContent(respData);
                //组装加密串
                if (RSAUtil.Verify(resultStr, signResult, SxfConfig.PublicKey))
                {
                    return true;
                }
                else
                {
                    //本地验证签名不成功
                    msg = "本地验证签名不成功";
                    return false;
                }
            }
            catch (Exception ex)
            {
                msg = "SXF返回解析失败," + ex.Message;
                return false;
            }
        }

        private static Hashtable GetQueryParam(string tradeno, int corpId)
        {
            Hashtable ht = new Hashtable();
            ht.Add("ordNo", tradeno);
            ht.Add("mno", SxfConfig.getMechId(corpId));
            return ht;
        }

        /// <summary>
        /// 查询订单支付结果
        /// </summary>
        /// <param name="tradeno"></param>
        /// <param name="CorpID"></param>
        /// <param name="orderStatus"></param>
        /// <returns></returns>
        public static bool Query(string tradeno, int CorpID, ref Hashtable respData)
        {
            Hashtable ht = GetQueryParam(tradeno, CorpID);
            string requestMessage = getRequestPara(ht);
            string responseJson = null;
            try
            {
                responseJson = RequestClient.Post(SxfConfig.QueryServiceUrl, requestMessage);
                Hashtable retHt = Newtonsoft.Json.JsonConvert.DeserializeObject<Hashtable>(responseJson);
                if (retHt == null)
                {
                    //Xcx.Lib.CLog.Write("SXF查询失败,返回：" + responseJson);
                    return false;
                }
                if (Convert.ToString(retHt["code"]) != "0000")
                {
                    //Xcx.Lib.CLog.Write("SXF查询失败,返回：" + responseJson);
                    return false;
                }
                respData = Newtonsoft.Json.JsonConvert.DeserializeObject<Hashtable>(Convert.ToString(retHt["respData"]));
                if (respData == null)
                {
                    //Xcx.Lib.CLog.Write("SXF查询失败,返回：" + responseJson);
                    return false;
                }
                if (Convert.ToString(respData["tranSts"]) != "SUCCESS")
                {
                    //Xcx.Lib.CLog.Write("SXF订单状态：" + CommFunc.ConvertToString(retHt["tranSts"]) + ",SXF查询返回：" + responseJson);
                    return false;
                }
                else
                {
                    //Xcx.Lib.CLog.Write("SXF订单状态：" + CommFunc.ConvertToString(retHt["tranSts"]) + ",成功");
                }
            }
            catch (Exception ex)
            {
                return false;
            }
            return true;
        }

        /// <summary>
        /// 随行付支付-聚合支付参数设置
        /// </summary>
        /// <param name="param"></param>
        /// <param name="amt"></param>
        /// <param name="tradeno"></param>
        /// <param name="xcxtype"></param>
        /// <returns></returns>
        private static Hashtable GetPayParam(int business_id, string amt, string ordNo, string sOpenid)
        {
            Hashtable ht = new Hashtable();
            string appid = "wxea7d284ff9b8d244";
            string sxf_mno = "399200819168726";
            appid = SxfConfig.getMiniProgramAppId(business_id);
            sxf_mno = SxfConfig.getMechId(business_id);
            ht.Add("ordNo", ordNo);
            ht.Add("mno", sxf_mno);
            ht.Add("amt", amt);
            ht.Add("subAppid", appid);
            ht.Add("payType", "WECHAT");
            ht.Add("payWay", "03");
            ht.Add("subject", "商品");
            ht.Add("tradeSource", "01");
            ht.Add("trmIp", GetLocalIp());
            ht.Add("userId", sOpenid);    //openid
            ht.Add("extend", "test");
            return ht;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        private static string getTimestamp()
        {
            DateTime NOW = DateTime.Now;
            return NOW.Year.ToString() +
                (NOW.Month.ToString().Length == 1 ? "0" + NOW.Month.ToString() : NOW.Month.ToString()) +
                (NOW.Day.ToString().Length == 1 ? "0" + NOW.Day.ToString() : NOW.Day.ToString()) +
                (NOW.Hour.ToString().Length == 1 ? "0" + NOW.Hour.ToString() : NOW.Hour.ToString()) +
                (NOW.Minute.ToString().Length == 1 ? "0" + NOW.Minute.ToString() : NOW.Minute.ToString()) +
                (NOW.Second.ToString().Length == 1 ? "0" + NOW.Second.ToString() : NOW.Second.ToString());
        }

        /// <summary>
        /// 获取签名
        /// </summary>
        /// <param name="ht"></param>
        /// <returns></returns>
        private static string getRequestPara(Hashtable ht)
        {
            ApiRequestBean ApiRequestBean = new ApiRequestBean();
            ApiRequestBean.orgId = "36208466";  //机构号
            ApiRequestBean.reqId = Guid.NewGuid().ToString().Replace("-", "");
            ApiRequestBean.signType = "RSA";
            ApiRequestBean.timestamp = getTimestamp();
            ApiRequestBean.version = "1.0";
            ApiRequestBean.reqData = ht;

            string rsaResult;
            string requestMessage = "";
            string result = PackReflectionEntity<ApiRequestBean>.GetEntityToString(ApiRequestBean);
            //签名
            rsaResult = RSAUtil.RSASign(result, SxfConfig.RsaPrivateKey);
            //实体付签名传给接口
            requestMessage = fillFullRequestMessage(rsaResult, ApiRequestBean);
            return requestMessage;
        }

        public static string GetLocalIp()
        {
            IPAddress localIp = null;

            try
            {
                IPAddress[] ipArray;
                ipArray = Dns.GetHostAddresses(Dns.GetHostName());
                localIp = ipArray.First(ip => ip.AddressFamily == AddressFamily.InterNetwork);

            }
            catch (Exception ex)
            {
                //异常处理
            }
            if (localIp == null)
            {
                localIp = IPAddress.Parse("127.0.0.1");
            }
            return localIp.ToString();
        }

        //解析返回支付结果并写入缓存队列
        public static bool getPayResult(string responseJson, string amt, string tradeno, ref string msg)
        {
            IDictionary<string, object> respData = null;
            try
            {
                respData = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, object>>(responseJson);
                if (respData["code"].ToString() != "0000")
                {
                    msg = respData["msg"].ToString();
                    return false;
                }

                string signResult = respData["sign"].ToString();
                msg = respData["msg"].ToString();
                respData.Remove("sign");
                //参数签名串
                string resultStr = RSAUtil.GetSignContent(respData);
                //组装加密串
                if (RSAUtil.Verify(resultStr, signResult, SxfConfig.PublicKey))
                {
                    //本地验证签名成功
                    //把等待支付完成订单号保存到缓存队列
                    WeChatPayQueryRequest payData = new WeChatPayQueryRequest();
                    payData = new WeChatPayQueryRequest
                    {
                        WIDout_trade_no = tradeno,
                        Amount = amt,
                        Random = new Random().Next(0, 1000).ToString(),
                    };

                    //把支付数据加入缓存并加入订单查询队列，付款成功写入单据完成时清除                        
                    var json = SerializerHelper.SerializeToString(payData);
                    return true;
                }
                else
                {
                    //本地验证签名不成功
                    msg = "本地验证签名不成功";
                    return false;
                }
            }
            catch (Exception ex)
            {
                msg = "SXF返回解析失败," + ex.Message;
                return false;
            }

        }

        /// <summary>
        /// 主动查询支付结果
        /// </summary>
        /// <param name="sThreadID"></param>
        public static bool GetQueryPayResult(string sThreadID)
        {


            return true;
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="queryResult"></param>
        /// <param name="requestMsgBody"></param>
        /// <returns></returns>
        private static string fillFullRequestMessage(string queryResult, ApiRequestBean requestMsgBody)
        {
            ApiRequestBeanNew data = new ApiRequestBeanNew();
            data.reqData = requestMsgBody.reqData;
            data.signType = requestMsgBody.signType;
            data.version = requestMsgBody.version;
            data.orgId = requestMsgBody.orgId;
            data.reqId = requestMsgBody.reqId;
            data.timestamp = requestMsgBody.timestamp;
            data.sign = queryResult;

            string result = Newtonsoft.Json.JsonConvert.SerializeObject(data);
            return result;
        }



        public static bool GetCreateOrderPayAppletScanPre(int shop_id, decimal total_fee, string out_trade_no, ref string msg, out Dictionary<string, object> Result)
        {
            // 查询商户号
            ArrayList list = DBHelper.Select("select  * from t_ShouKuanElfin where FCorpID=@shopID", new List<SqlParameter>(){
                new SqlParameter("@shopID", shop_id)
            }.ToArray(), DBHelper.ConnMaster);

            if (list.Count is 0)
            {
                Result = new Dictionary<string, object> {
                    { "msg","未查询到商户!"}
                };
                msg = "SXF失败," + "未查询到商户!";
                return false;
            }
            Hashtable skht = list[0] as Hashtable;
            string m_FMerchantCode = skht["FMerchantCode"] as string;
            if (string.IsNullOrWhiteSpace(m_FMerchantCode))
            {
                Result = new Dictionary<string, object> {
                    { "msg","未配置商户号!"}
                };
                msg = "SXF失败," + "未配置商户号!";
                return false;
            }


            Result = new Dictionary<string, object>();//返回支付信息
            Hashtable ht = new Hashtable(); //创建一个Hashtable实例
            ht = GetPayParamAppletScanPre(m_FMerchantCode, total_fee.ToString(), out_trade_no);
            string requestMessage = getRequestPara(ht);
            string responseJson = null;
            try
            {
                Console.WriteLine($"requestMessage==>{requestMessage.ToString()}");
                responseJson = RequestClient.Post(SxfConfig.PayAppletScanPreUrl, requestMessage);
                Result = (Dictionary<String, Object>)LFTPayDoing.Json2Dictionary(responseJson);
                Console.WriteLine($"Result==>{responseJson.ToString()}");
                return true;
            }
            catch (Exception ex)
            {
                msg = "SXF失败," + ex.Message;
                return false;
            }
        }

        /// <summary>
        /// 随行付支付-聚合支付参数设置
        /// </summary>
        /// <param name="param"></param>
        /// <param name="amt"></param>
        /// <param name="tradeno"></param>
        /// <param name="xcxtype"></param>
        /// <returns></returns>
        private static Hashtable GetPayParamAppletScanPre(string sxf_mno, string amt, string ordNo)
        {
            Hashtable ht = new Hashtable();
            ht.Add("ordNo", ordNo);
            ht.Add("mno", sxf_mno);
            ht.Add("amt", amt);
            //ht.Add("appletSource", "00");//小程序插件
            ht.Add("appletSource", "01");//半屏支付
            ht.Add("trmIp", GetLocalIp());
            ht.Add("subject", "商品");
            //ht.Add("notifyUrl", "");//回调地址            
            return ht;
        }




    }
}
